package com.yfbao.horizon.demo;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockCondition {

    public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        Condition producerCondition = lock.newCondition();
        Condition consumerCondition = lock.newCondition();

        Resource2 resource = new Resource2(lock, producerCondition, consumerCondition);

        //生产者线程
        ProducerThread2 producer1 = new ProducerThread2(resource);
        ProducerThread2 producer2 = new ProducerThread2(resource);
        ProducerThread2 producer3 = new ProducerThread2(resource);

        //消费者线程
        ConsumerThread2 consumer1 = new ConsumerThread2(resource);
        ConsumerThread2 consumer2 = new ConsumerThread2(resource);
        ConsumerThread2 consumer3 = new ConsumerThread2(resource);

        producer1.start();
        producer2.start();
        producer3.start();
        consumer1.start();
        consumer2.start();
        consumer3.start();
    }

    static class ConsumerThread2 extends Thread {
        private final Resource2 resource;

        public ConsumerThread2(Resource2 resource) {
            this.resource = resource;
            setName("消费者");
        }

        public void run() {
            while (true) {
                try {
                    Thread.sleep((long) (1000 * Math.random()));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.remove();
            }
        }
    }

    static class ProducerThread2 extends Thread {
        private final Resource2 resource;

        public ProducerThread2(Resource2 resource) {
            this.resource = resource;
            setName("生产者");
        }

        public void run() {
            while (true) {
                try {
                    Thread.sleep((long) (1000 * Math.random()));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                resource.add();
            }
        }
    }

    static class Resource2 {
        private int currentCount = 0;//当前资源数量
        private final Lock lock;
        private final Condition producerCondition;
        private final Condition consumerCondition;

        public Resource2(Lock lock, Condition producerCondition, Condition consumerCondition) {
            this.lock = lock;
            this.producerCondition = producerCondition;
            this.consumerCondition = consumerCondition;

        }

        /**
         * 向资源池中添加资源
         */
        public void add() {
            lock.lock();
            try {
                //资源池中允许存放的资源数目
                int maxCount = 10;
                if (currentCount < maxCount) {
                    currentCount++;
                    System.out.println(Thread.currentThread().getName() +
                            "生产一件资源,当前资源池有" + currentCount + "个");
                    //唤醒等待的消费者
                    consumerCondition.signalAll();
                } else {
                    //让生产者线程等待
                    try {
                        producerCondition.await();
                        System.out.println(Thread.currentThread().getName() + "线程进入等待");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                lock.unlock();
            }
        }

        /**
         * 从资源池中取走资源
         */
        public void remove() {
            lock.lock();
            try {
                if (currentCount > 0) {
                    currentCount--;
                    System.out.println("消费者" + Thread.currentThread().getName()
                            + "消耗一件资源," + "当前资源池有" + currentCount + "个");
                    //唤醒等待的生产者
                    producerCondition.signalAll();
                } else {
                    try {
                        //让消费者等待
                        consumerCondition.await();
                        System.out.println(Thread.currentThread().getName() + "线程进入等待");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            } finally {
                lock.unlock();
            }
        }

    }

}

